package com.locus.locus.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.locus.locus.client.Servidor;
import com.locus.locus.client.dados.ConfiguracaoBoxWrapper;
import com.locus.locus.client.dados.ConfiguracaoConjuntoBoxesWrapper;
import com.locus.locus.client.dados.EstabelecimentoWrapper;
import com.locus.locus.client.dados.ConjuntoBoxesWrapper;
import com.locus.locus.client.dados.LocalizacaoWrapper;
import com.locus.locus.client.dados.SiteWrapper;
import com.locus.locus.client.dados.TweetWrapper;
import com.locus.locus.client.dados.UsuarioLocusWrapper;
import com.locus.locus.server.dados.ConfiguracaoBox;
import com.locus.locus.server.dados.DAO;
import com.locus.locus.server.dados.Estabelecimento;
import com.locus.locus.server.dados.Localizacao;
import com.locus.locus.server.dados.UsuarioLocus;

@SuppressWarnings("serial")
public class ServidorImpl extends RemoteServiceServlet implements Servidor {
	
	static{
		if(DAO.buscar(UsuarioLocus.class, "nome == arthurelihimas") == null){
			UsuarioLocus administrador = new UsuarioLocus("arthurelihimas", true, new ArrayList<Estabelecimento>());
			DAO.salvar(administrador);
		}
	}

	@Override
	public UsuarioLocusWrapper buscarUsuario(String urlDestino) {
		final UsuarioLocusWrapper usuarioWrapper;
		final UserService userService = UserServiceFactory.getUserService();
		
		User currentUser = userService.getCurrentUser();
		
		if(currentUser != null){
			UsuarioLocus usuarioLocus = DAO.buscarTransiente(UsuarioLocus.class, "nome == " + currentUser.getNickname());
			if(usuarioLocus == null){
				usuarioLocus = new UsuarioLocus(currentUser.getNickname(), false, new ArrayList<Estabelecimento>(0));
				DAO.salvar(usuarioLocus);
			}
			usuarioWrapper = usuarioLocus.gerarWrapper();
			usuarioWrapper.setLogado(true);
			usuarioWrapper.setUrlLogout(userService.createLogoutURL(urlDestino));
		}else{
			usuarioWrapper = new UsuarioLocusWrapper();
			usuarioWrapper.setLogado(false);
			usuarioWrapper.setUrlLogin(userService.createLoginURL(urlDestino));
		}
		
		return usuarioWrapper;
	}

	@Override
	public List<UsuarioLocusWrapper> buscarUsusarios() throws IOException {
		if(this.verificarAdmin()){
			return DAO.buscarTodos(UsuarioLocus.class);
		}else{
			return null;
		}
	}

	private boolean verificarAdmin() throws IOException {
		final User currentUser = UserServiceFactory.getUserService().getCurrentUser();
		final String nome;
		final UsuarioLocus usuario;
		
		if(currentUser != null){
			nome = currentUser.getNickname();
			usuario = DAO.buscar(UsuarioLocus.class, "nome == " + nome);
		}else{
			usuario = null;
		}
		if(usuario == null || !usuario.isAdministradorLocus()){
			final HttpServletResponse response = this.getThreadLocalResponse();
			response.sendRedirect("/");
			return false;
		}
		return true;
	}

	@Override
	public List<UsuarioLocusWrapper> buscarUsusarios(String where) throws IOException {
		this.verificarAdmin();
		return DAO.buscarTodos(UsuarioLocus.class, where);
	}

	@Override
	public void inserirUsuario(UsuarioLocusWrapper usuario) throws IOException {
		this.verificarAdmin();
		DAO.salvar(new UsuarioLocus(usuario));
	}

	@Override
	public void excluirUsuario(UsuarioLocusWrapper usuario) throws IOException {
		this.verificarAdmin();
		DAO.excluir(UsuarioLocus.class, usuario.getChave());
	}

	@Override
	public void inserirExtabelecimento(EstabelecimentoWrapper estabelecimento) throws IOException {
		this.verificarAdmin();
		DAO.salvarEstabelecimento(new Estabelecimento(estabelecimento));
	}

	@Override
	public void excluirExtabelecimento(EstabelecimentoWrapper estabelecimento) throws IOException {
		this.verificarAdmin();
		DAO.excluir(Estabelecimento.class, estabelecimento.getChave());
	}

	@Override
	public List<EstabelecimentoWrapper> buscarEstabelecimentos() throws IOException {
		this.verificarAdmin();
		return DAO.buscarTodos(Estabelecimento.class);
	}

	@Override
	public ConfiguracaoConjuntoBoxesWrapper buscarConfiguracaoConjuntoBoxes() throws IOException {
		this.verificarAdmin();
		return DAO.getConfiguracaoBoxes().gerarWrapper();
	}
	
	public void inserirBoxConjuntoConfiguracao(ConfiguracaoBoxWrapper box) throws IOException {
		this.verificarAdmin();
		DAO.inserirBoxConjunto(new ConfiguracaoBox(box));
	}
	
	@Override
	public void excluirBoxConjuntoConfiguracao(ConfiguracaoBoxWrapper box) throws IOException {
		this.verificarAdmin();
		DAO.excluirBoxConjunto(new ConfiguracaoBox(box));
	}

	@Override
	public List<ConfiguracaoBoxWrapper> buscarConfiguracoesBoxes() throws IOException {
		this.verificarAdmin();
		return DAO.buscarTransiente(ConfiguracaoBox.class);
	}

	@Override
	public void excluirConfiguracoesBox(ConfiguracaoBoxWrapper box) throws IOException {
		this.verificarAdmin();
		DAO.excluir(ConfiguracaoBox.class, box.getChave());
	}

	@Override
	public void inserirConfiguracoesBox(ConfiguracaoBoxWrapper box) throws IOException {
		this.verificarAdmin();
		DAO.salvar(new ConfiguracaoBox(box));
	}

	@Override
	public ConjuntoBoxesWrapper buscarConjuntoBoxes() throws IOException {
		return DAO.buscarBoxes().gerarWrapper();
	}

	@Override
	public SiteWrapper buscarSite(String idSite) {
		final SiteWrapper site = new SiteWrapper();
		final List<TweetWrapper> tweets = DAO.buscarTweets(idSite);
		final Estabelecimento estabelecimento = DAO.buscarPorId(Estabelecimento.class, KeyFactory.stringToKey(idSite));
		final ArrayList<LocalizacaoWrapper> localizacoes = new ArrayList<LocalizacaoWrapper>(estabelecimento.getLocalizacoes().size());
		
		site.setNomeSite(estabelecimento.getNomeSite());
		site.setInformacoes(estabelecimento.getInformacoes());
		site.setTweets(tweets);
		site.setLocalizacoes(localizacoes);
		for(Localizacao localizacao:estabelecimento.getLocalizacoes()){
			localizacoes.add(localizacao.gerarWrapper());
		}
		
		return site;
	}

	@Override
	public void wipeData() throws IOException {
		this.verificarAdmin();
		DAO.excluirTodos();
	}
}
